wrmsrl(MSR_K8_SYSCFG, syscfg);
}
+static void __devinit amd_get_topology(struct cpuinfo_x86 *c)
+{
+#ifdef CONFIG_X86_HT
+ int cpu;
+ unsigned bits;
+
+ if (c->x86_max_cores <= 1)
+ return;
+ /*
+ * On a AMD multi core setup the lower bits of the APIC id
+ * distingush the cores.
+ */
+ cpu = smp_processor_id();
+ bits = (cpuid_ecx(0x80000008) >> 12) & 0xf;
+
+ if (bits == 0) {
+ while ((1 << bits) < c->x86_max_cores)
+ bits++;
+ }
+
+ /* Low order bits define the core id */
+ c->cpu_core_id = c->phys_proc_id & ((1<<bits)-1);
+ /* Convert local APIC ID into the socket ID */
+ c->phys_proc_id >>= bits;
+ /* Collect compute unit ID if available */
+ if (cpu_has(c, X86_FEATURE_TOPOEXT)) {
+ u32 eax, ebx, ecx, edx;
+
+ cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
+ c->compute_unit_id = ebx & 0xFF;
+ c->x86_num_siblings = ((ebx >> 8) & 0x3) + 1;
+ }
+
+ if (opt_cpu_info)
+ printk("CPU %d(%d) -> Processor %d, %s %d\n",
+ cpu, c->x86_max_cores, c->phys_proc_id,
+ cpu_has(c, X86_FEATURE_TOPOEXT) ? "Compute Unit" :
+ "Core",
+ cpu_has(c, X86_FEATURE_TOPOEXT) ? c->compute_unit_id :
+ c->cpu_core_id);
+#endif
+}
+
static void __devinit init_amd(struct cpuinfo_x86 *c)
{
u32 l, h;
}
}
-#ifdef CONFIG_X86_HT
- /*
- * On a AMD multi core setup the lower bits of the APIC id
- * distingush the cores.
- */
- if (c->x86_max_cores > 1) {
- int cpu = smp_processor_id();
- unsigned bits = (cpuid_ecx(0x80000008) >> 12) & 0xf;
-
- if (bits == 0) {
- while ((1 << bits) < c->x86_max_cores)
- bits++;
- }
- c->cpu_core_id = c->phys_proc_id & ((1<<bits)-1);
- c->phys_proc_id >>= bits;
- if (opt_cpu_info)
- printk("CPU %d(%d) -> Core %d\n",
- cpu, c->x86_max_cores, c->cpu_core_id);
- }
-#endif
+ amd_get_topology(c);
/* Pointless to use MWAIT on Family10 as it does not deep sleep. */
if (c->x86 >= 0x10 && !force_mwait)
c->x86_clflush_size = 0;
c->phys_proc_id = BAD_APICID;
c->cpu_core_id = BAD_APICID;
+ c->compute_unit_id = BAD_APICID;
memset(&c->x86_capability, 0, sizeof c->x86_capability);
generic_identify(c);
/* CPUs for which sibling maps can be computed. */
static cpumask_t cpu_sibling_setup_map;
+static void link_thread_siblings(int cpu1, int cpu2)
+{
+ cpu_set(cpu1, per_cpu(cpu_sibling_map, cpu2));
+ cpu_set(cpu2, per_cpu(cpu_sibling_map, cpu1));
+ cpu_set(cpu1, per_cpu(cpu_core_map, cpu2));
+ cpu_set(cpu2, per_cpu(cpu_core_map, cpu1));
+}
+
static void set_cpu_sibling_map(int cpu)
{
int i;
{
for_each_cpu_mask ( i, cpu_sibling_setup_map )
{
- if ( (c[cpu].phys_proc_id == c[i].phys_proc_id) &&
- (c[cpu].cpu_core_id == c[i].cpu_core_id) )
- {
- cpu_set(i, per_cpu(cpu_sibling_map, cpu));
- cpu_set(cpu, per_cpu(cpu_sibling_map, i));
- cpu_set(i, per_cpu(cpu_core_map, cpu));
- cpu_set(cpu, per_cpu(cpu_core_map, i));
+ if ( cpu_has(c, X86_FEATURE_TOPOEXT) ) {
+ if ( (c[cpu].phys_proc_id == c[i].phys_proc_id) &&
+ (c[cpu].compute_unit_id == c[i].compute_unit_id) )
+ link_thread_siblings(cpu, i);
+ } else if ( (c[cpu].phys_proc_id == c[i].phys_proc_id) &&
+ (c[cpu].cpu_core_id == c[i].cpu_core_id) ) {
+ link_thread_siblings(cpu, i);
}
}
}
cpus_clear(per_cpu(cpu_core_map, cpu));
c[cpu].phys_proc_id = BAD_APICID;
c[cpu].cpu_core_id = BAD_APICID;
+ c[cpu].compute_unit_id = BAD_APICID;
cpu_clear(cpu, cpu_sibling_setup_map);
}
__u32 x86_max_cores; /* cpuid returned max cores value */
__u32 booted_cores; /* number of cores as seen by OS */
__u32 x86_num_siblings; /* cpuid logical cpus per chip value */
+ __u32 apicid;
int phys_proc_id; /* package ID of each logical CPU */
int cpu_core_id; /* core ID of each logical CPU*/
- __u32 apicid;
+ int compute_unit_id; /* AMD compute unit ID of each logical CPU */
unsigned short x86_clflush_size;
} __cacheline_aligned;